package com.jjkj.environmental.environmental.utils.pull

import android.util.Xml
import com.jjkj.environmental.environmental.bean.model.CarInfo
import com.jjkj.environmental.environmental.bean.request.Condition
import com.jjkj.environmental.environmental.bean.response.SoapResponse
import com.jjkj.environmental.environmental.exception.PullConverterException
import com.jjkj.environmental.environmental.utils.MyLog
import com.jjkj.environmental.environmental.utils.NameSpace
import com.jjkj.environmental.environmental.utils.XmlTagName
import org.xmlpull.v1.XmlPullParser
import java.io.StringReader
import java.io.StringWriter
import java.util.*


object PullConverter {

    /*把WebService请求对象转化为soap请求xml结构*/
    fun convertRequest(obj: Any): String {
        val serializer = Xml.newSerializer()
        val writer = StringWriter()
        serializer.setOutput(writer)
        /*处理soap请求xml结果最外层soap:Envelope和soap:Body开始*/
        serializer.startDocument("utf-8", null)
        serializer.setPrefix("soap", "http://schemas.xmlsoap.org/soap/envelope/")
        serializer.setPrefix("xsi", "http://www.w3.org/2001/XMLSchema-instance")
        serializer.setPrefix("xsd", "http://www.w3.org/2001/XMLSchema")
        serializer.startTag(null, "soap:Envelope")
        serializer.startTag(null, "soap:Body")
        /*开始处理soap:Body里面的请求对象*/
        val clazz = obj::class.java
        //获取实体类上面的注解属性
        val nameSpace = clazz.getAnnotation(NameSpace::class.java)
                ?: throw PullConverterException("请求实体类需要NameSpace注解")
        //请求实体类开始标签处理
        serializer.startTag(null, nameSpace.tag)
        serializer.attribute(null, "xmlns", nameSpace.nameSpace)
        //请求实体类字段处理
        clazz.declaredFields.forEach {
            val tagName = it.getAnnotation(XmlTagName::class.java)
            it.isAccessible = true
            //判断字段值为String且字段有注解XmlTagName
            if (tagName != null && it.get(obj) is String) {
                serializer.startTag(null, tagName.tag)
                serializer.text(it.get(obj) as String)
                serializer.endTag(null, tagName.tag)
            }
        }
        //请求实体类结束标签处理
        serializer.endTag(null, nameSpace.tag)
        /*处理soap请求xml结果最外层soap:Envelope和soap:Body结束*/
        serializer.endTag(null, "soap:Body")
        serializer.endTag(null, "soap:Envelope")
        serializer.endDocument()
        return writer.toString()
    }


    /*把WebService请求结果转化为SoapResponse对象*/
    fun convertResponse(xml: String): SoapResponse {
        val resp = SoapResponse()
        resp.body = xml.substring(xml.indexOf("<return>") + "<return>".length, xml.indexOf("</return>"))
        return resp
    }

    fun <T> convertCondition(condition: Condition<T>): String {

        val serializer = Xml.newSerializer()
        val writer = StringWriter()
        serializer.setOutput(writer)
        val bean = condition.bean as Any
        val beanClass = bean::class.java
        val tag = beanClass.getAnnotation(XmlTagName::class.java)
                ?: throw PullConverterException("类需要XmlTagName注解")
        /*Condition外层开始标签*/
        serializer.startDocument("utf-8", null)
        serializer.startTag(null, "root")
        serializer.startTag(null, tag.tag)

        /*Condition对象字段处理*/
        val fields = beanClass.declaredFields
        fields.forEach {
            val annotation = it.getAnnotation(XmlTagName::class.java)
            if (annotation != null) {
                it.isAccessible = true
                val value = it.get(condition.bean!!) as String
                if (value != "") {
                    serializer.startTag(null, annotation.tag)
                    serializer.text(it.get(condition.bean!!) as String)
                    serializer.endTag(null, annotation.tag)
                }
            }
        }
        /*Condition外层结束标签*/
        serializer.endTag(null, tag.tag)
        serializer.endTag(null, "root")
        serializer.endDocument()
        MyLog.i(writer.toString())
        return writer.toString()
    }

    fun xml2CarInfoList(xml: String): List<CarInfo> {
        val data = ArrayList<CarInfo>()
        val reader = StringReader(xml)
        val parser = Xml.newPullParser()
        var carInfo: CarInfo? = null
        parser.setInput(reader)
        var eventType = parser.eventType
        while (XmlPullParser.END_DOCUMENT != eventType) {
            when (eventType) {
                XmlPullParser.START_TAG -> if (parser.name == "vehispara") {
                    carInfo = CarInfo()
                } else if (carInfo != null) run {
                    val field = CarInfo::class.java.getDeclaredField(parser.name)
                    field.isAccessible = true
                    field.set(carInfo, parser.nextText())
                }
                XmlPullParser.END_TAG -> if (parser.name == "vehispara") {
                    data.add(carInfo!!)
                    carInfo = null
                }
            }
            eventType = parser.next()
        }
        return data
    }
}